package gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;

import dao.DataLoader;
import data.Data.TeamID;
import data.Team;
import engine.GameEngine;
import gui.teamEditor.TeamEditor;
import gui.util.ExtensionFileFilter;

/**
 * This class implements the basic game menu functionality needed. It will take
 * care of forwarding what is needed to the engine.
 * 
 * @author Julien
 * 
 */
public class GameMenuBar extends JMenuBar implements ActionListener {
	private static final long serialVersionUID = -5007993978110777297L;

	/**
	 * Instance.
	 */
	private static GameMenuBar instance;

	// Top-level menus
	private JMenu m_game = new JMenu("Game");
	private JMenu m_debug = new JMenu("Debug");

	// Game submenu
	private JMenuItem m_startGame = new JMenuItem("Start game");
	private JMenuItem m_selTeamA = new JMenuItem("Select team A");
	private JCheckBoxMenuItem m_aiTeamA = new JCheckBoxMenuItem("Team A AI controlled");
	private JMenuItem m_selTeamB = new JMenuItem("Select team B");
	private JCheckBoxMenuItem m_aiTeamB = new JCheckBoxMenuItem("Team B AI controlled");
	private JCheckBoxMenuItem m_autoTeamSelect = new JCheckBoxMenuItem("Auto select last teams");
	private JMenuItem m_load = new JMenuItem("Load Game");
	private JMenuItem m_save = new JMenuItem("Save Game");
	private JMenuItem m_startEditor = new JMenuItem("Start Team Editor");
	private JMenuItem m_quit = new JMenuItem("Quit");

	// Debug submenu
	private JMenuItem m_updateMap = new JMenuItem("Force map update");
	private JMenuItem m_showTextMap = new JMenuItem("Show text map");

	// File chooser
	final JFileChooser m_fileChooser = new JFileChooser("data");

	// Internal data
	// FIXME: The menu bar should probably NOT keep a reference of the teams
	// private Team m_teamA = null;
	// private Team m_teamB = null;

	private JFrame m_parent = null;

	/**
	 * Constructor for the menu object.
	 * 
	 * @param parent
	 *            The frame holding the menu (needed for correct close behavior)
	 */
	public GameMenuBar(final PitchGUI G, final JFrame parent) {
		super();
		GameMenuBar.instance = this;

		m_aiTeamA.setState(DataLoader.getInstance().isTeamAAIControlled());
		m_aiTeamB.setState(DataLoader.getInstance().isTeamBAIControlled());

		m_autoTeamSelect.setState(DataLoader.getInstance().isTeamAutoSelect());

		m_game.setMnemonic(KeyEvent.VK_G);

		m_save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
		m_load.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
		m_quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));

		m_game.add(m_startGame);
		m_game.add(m_selTeamA);
		m_game.add(m_aiTeamA);
		m_game.add(m_selTeamB);
		m_game.add(m_aiTeamB);
		m_game.add(m_autoTeamSelect);
		m_game.add(m_save);
		m_game.add(m_load);
		m_game.add(m_quit);

		add(m_game);

		m_debug.setMnemonic(KeyEvent.VK_D);

		m_updateMap.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, ActionEvent.CTRL_MASK));

		m_debug.add(m_updateMap);
		m_debug.add(m_showTextMap);

		add(m_debug);

		// Add menu callbacks
		m_startGame.addActionListener(this);
		m_selTeamA.addActionListener(this);
		m_selTeamB.addActionListener(this);
		m_aiTeamB.addActionListener(this);
		m_load.addActionListener(this);
		m_save.addActionListener(this);
		m_startEditor.addActionListener(this);
		m_quit.addActionListener(this);
		// m_startGame.setEnabled(true);

		m_updateMap.addActionListener(this);
		m_showTextMap.addActionListener(this);

		m_parent = parent;
	}

	/**
	 * Getter for the "instance" property.
	 * 
	 * @return the instance
	 */
	public static GameMenuBar getInstance() {
		return instance;
	}

	/**
	 * IS team B AI controlled.
	 * 
	 * @return team B AI controlled
	 */
	public boolean isTeamBAiControlled() {
		return m_aiTeamB.getState();
	}

	/**
	 * IS team A AI controlled.
	 * 
	 * @return team A AI controlled
	 */
	public boolean isTeamAAiControlled() {
		return m_aiTeamA.getState();
	}

	/**
	 * Callback mechanism implementation. Is called when any menu item is
	 * pushed.
	 */
	@Override
	public void actionPerformed(final ActionEvent event) {
		Object source = event.getSource();
		if (source == m_startGame) {
			m_selTeamA.setEnabled(false);
			m_selTeamB.setEnabled(false);
			GameEngine.createInstance().startNewGame(DataLoader.getInstance().getTeamA(), DataLoader.getInstance().getTeamB());
		} else if (source == m_selTeamA || source == m_selTeamB) {
			// Open a standard load file dialog, looking for XML files
			int returnVal = m_fileChooser.showOpenDialog(this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = m_fileChooser.getSelectedFile();
				DataLoader.getInstance().loadTeam(source == m_selTeamA ? TeamID.TEAM_A : TeamID.TEAM_B, file);
			}
		} else if (source == m_save) {
			JFileChooser fileChooser = new JFileChooser("data/save");
			int returnValue = fileChooser.showSaveDialog(this);
			if (returnValue == JFileChooser.APPROVE_OPTION) {
				// append the extension if the user didn't write it
				String path = fileChooser.getSelectedFile().getAbsolutePath();
				if (!path.toLowerCase().endsWith(".sav")) {
					path += ".sav";
				}
				GameEngine.getInstance().saveGame(path);
			}
		} else if (source == m_load) {
			JFileChooser fileChooser = new JFileChooser("data/save");
			fileChooser.setFileFilter(new ExtensionFileFilter("Save Games", "SAV"));
			fileChooser.setAcceptAllFileFilterUsed(false);
			int returnValue = fileChooser.showOpenDialog(this);
			if (returnValue == JFileChooser.APPROVE_OPTION) {
				GameEngine.getInstance().loadGame(fileChooser.getSelectedFile().getAbsolutePath());
			}
		} else if (source == m_startEditor) {
			new TeamEditor();
		} else if (source == m_quit) {
			m_parent.dispose();
		} else if (source == m_updateMap) {
			GameEngine.getInstance().updateMap();
		} else if (source == m_showTextMap) {
			System.out.println(GameEngine.getInstance().showTextMap());
		}
	}

	/**
	 * Shows a message.
	 * 
	 * @param title
	 *            title
	 * @param message
	 *            message text
	 * @param errorMessage
	 *            is error message
	 */
	public void showMessage(final String title, final String message, final boolean errorMessage) {
		JOptionPane.showMessageDialog(this, message, title, errorMessage ? JOptionPane.NO_OPTION : JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * Sets selected team info.
	 * 
	 * @param id
	 *            team id
	 * @param team
	 *            team
	 */
	public void setSelectedTeam(final TeamID id, final Team team) {
		if (id == TeamID.TEAM_A) {
			m_selTeamA.setText("Select team A (" + team.getName() + ")");
		} else {
			m_selTeamB.setText("Select team B (" + team.getName() + ")");
		}
	}
}
